﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DevExpress.XtraEditors.Repository;
using DevExpress.XtraEditors;
using System.ComponentModel;
using DevExpress.XtraEditors.Registrator;
using DevExpress.XtraTreeList;
using System.Windows.Forms;
using DevExpress.XtraTreeList.Nodes;
using System.Data;

namespace ProgNetDxComponents.Controls.Editors
{

    public class TreeLookUpEditPopUpControl : PopupContainerControl
    {
        public TreeLookUpEditPopUpControl()
            : base()
        {
            InitializeComponent();
            this.Controls.Add(this.treeList);
            this.Controls.Add(this.panelControl1);
            treeList.ForceInitialize();
            MultiSelect = false;
        }

        private string _MultiSelectSeparator = ",";
        private string _DisplayMember;
        public bool MultiSelect
        {
            get { return TreeList.OptionsSelection.MultiSelect; }
            set
            {
                TreeList.OptionsSelection.MultiSelect = value;
                TreeList.OptionsView.ShowCheckBoxes = value;
                panelControl1.Visible = value;
            }
        }
        public string MultiSelectSeparator
        {
            get { return _MultiSelectSeparator; }
            set { _MultiSelectSeparator = value; }
        }
        public string DisplayMember
        {
            get
            {
                if (String.IsNullOrEmpty(_DisplayMember))
                    return treeList.KeyFieldName;
                return _DisplayMember;
            }
            set { _DisplayMember = value; }
        }

        private PanelControl panelControl1;
        private SimpleButton btnOK;
        private SimpleButton btnCancel;
        private List<TreeListNode> CheckedNodes = new List<TreeListNode>();
         
        private DevExpress.XtraTreeList.TreeList treeList;
        public DevExpress.XtraTreeList.TreeList TreeList
        {
            get
            {
                if (treeList.BindingContext == null)
                {
                    if (this.OwnerEdit != null && this.OwnerEdit.BindingContext != null)
                        treeList.BindingContext = this.OwnerEdit.BindingContext;
                    else if (Form.ActiveForm != null && Form.ActiveForm.BindingContext != null)
                    {
                        treeList.BindingContext = Form.ActiveForm.BindingContext;
                    }
                }
                return treeList;
            }
        }

        private void InitializeComponent()
        {
            this.treeList = new DevExpress.XtraTreeList.TreeList();
            this.panelControl1 = new DevExpress.XtraEditors.PanelControl();
            this.btnCancel = new DevExpress.XtraEditors.SimpleButton();
            this.btnOK = new DevExpress.XtraEditors.SimpleButton();
            ((System.ComponentModel.ISupportInitialize)(this.treeList)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.panelControl1)).BeginInit();
            this.panelControl1.SuspendLayout();
            this.SuspendLayout();
            // 
            // treeList
            // 
            this.treeList.Dock = System.Windows.Forms.DockStyle.Fill;
            this.treeList.Location = new System.Drawing.Point(0, 0);
            this.treeList.Name = "treeList";
            this.treeList.OptionsSelection.MultiSelect = true;
            this.treeList.OptionsView.ShowCheckBoxes = true;
            this.treeList.Size = new System.Drawing.Size(257, 127);
            this.treeList.TabIndex = 0;
            this.treeList.EditorKeyDown += new System.Windows.Forms.KeyEventHandler(this.treeList_EditorKeyDown);
            this.treeList.DoubleClick += new System.EventHandler(this.treeList_DoubleClick);
            this.treeList.AfterCheckNode += new NodeEventHandler(treeList_AfterCheckNode);
            // 
            // panelControl1
            // 
            this.panelControl1.Controls.Add(this.btnOK);
            this.panelControl1.Controls.Add(this.btnCancel);
            this.panelControl1.Dock = System.Windows.Forms.DockStyle.Bottom;
            this.panelControl1.Location = new System.Drawing.Point(0, 127);
            this.panelControl1.Name = "panelControl1";
            this.panelControl1.Size = new System.Drawing.Size(257, 27);
            this.panelControl1.TabIndex = 1;
            // 
            // btnCancel
            // 
            this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
            this.btnCancel.Location = new System.Drawing.Point(206, 3);
            this.btnCancel.Name = "btnCancel";
            this.btnCancel.Size = new System.Drawing.Size(48, 19);
            this.btnCancel.TabIndex = 2;
            this.btnCancel.Text = "Cancel";
            this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
            // 
            // btnOK
            // 
            this.btnOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
            this.btnOK.Location = new System.Drawing.Point(152, 3);
            this.btnOK.Name = "btnOK";
            this.btnOK.Size = new System.Drawing.Size(48, 19);
            this.btnOK.TabIndex = 1;
            this.btnOK.Text = "OK";
            this.btnOK.Click += new System.EventHandler(this.btnOK_Click);
            // 
            // TreeLookUpEditPopUpControl
            // 
           
            this.Name = "TreeLookUpEditPopUpControl";
            this.Size = new System.Drawing.Size(257, 154);
            ((System.ComponentModel.ISupportInitialize)(this.treeList)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.panelControl1)).EndInit();
            this.panelControl1.ResumeLayout(false);
            this.ResumeLayout(false);
        }

        void treeList_AfterCheckNode(object sender, NodeEventArgs e)
        {
            AddCheckedNode(e.Node);
        }
        private void AddCheckedNode(TreeListNode node)
        {
            if (node != null)
            {
                if (node.Checked)
                {
                    if (!CheckedNodes.Contains(node))
                    {
                        CheckedNodes.Add(node);
                    }
                }
                else
                {
                    if (CheckedNodes.Contains(node))
                    {
                        CheckedNodes.Remove(node);
                    }
                }
            }
        }
        private void treeList_EditorKeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
        {
            if (!MultiSelect)
            {
                if (e.KeyCode == System.Windows.Forms.Keys.Enter)
                {
                    SetEditValue(false);
                }
                if (e.KeyCode == System.Windows.Forms.Keys.Delete ||
                    e.KeyCode == System.Windows.Forms.Keys.Back)
                {
                    SetEditValue(true);
                }
            }
        }
        
        private void treeList_DoubleClick(object sender, EventArgs e)
        {
            if(!MultiSelect)
            SetEditValue(false);
        }

        private void SetEditValue(bool clear)
        {
            if (treeList.FocusedNode != null && !clear)
            {
                this.OwnerEdit.EditValue = treeList.FocusedNode.GetValue(treeList.KeyFieldName);
            }
            else
            {
                this.OwnerEdit.EditValue = null;
            }
            this.OwnerEdit.ClosePopup();
        }

        private DataTable GetTreeTable()
        {
            if (treeList.DataSource is DataTable)
                return treeList.DataSource as DataTable;
            if (treeList.DataSource is DataView)
                return (treeList.DataSource as DataView).Table;
            return null;
        }

        public void SelectItem(object item)
        {
            DevExpress.XtraTreeList.Nodes.TreeListNode node = null;
            treeList.CollapseAll();
            if (!MultiSelect)
            {
                node = treeList.FindNodeByKeyID(item);
                if (node == null)
                {
                    treeList.FocusedNode = treeList.Nodes.FirstNode;
                }
                else
                {
                    treeList.FocusedNode = node;
                }
            }
            else
            {
                foreach (TreeListNode n in CheckedNodes)
                {
                    n.Checked = false;
                }
                CheckedNodes.Clear();
                string str = item.AsString();
                string[]parts = str.Split(new string[] { MultiSelectSeparator }, StringSplitOptions.RemoveEmptyEntries);
                DataTable d = GetTreeTable();
                    Type t = typeof(string);
                if(d!=null)
                    t = d.Columns[treeList.KeyFieldName].DataType;

                foreach (string s in parts)
                {
                    try
                    {
                        node = treeList.FindNodeByKeyID(Convert.ChangeType(s, t));
                        if (node != null)
                        {
                            node.Checked = true;
                            AddCheckedNode(node);
                        }
                    }
                    catch { }
                }
            }
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            foreach (TreeListNode n in CheckedNodes)
            {
                n.Checked = false;
            }
            CheckedNodes.Clear();
            this.OwnerEdit.ClosePopup();
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            string str = "";
            foreach (TreeListNode n in CheckedNodes)
            {
                 if(!string.IsNullOrEmpty(str))
                     str += MultiSelectSeparator;
                str += n.GetValue(treeList.KeyFieldName).ToString();
            }
            this.OwnerEdit.EditValue = str;
            this.OwnerEdit.ClosePopup();
        }

        internal string GetDisplayValue(object editValue)
        {
            string result = editValue.AsString();
            if (editValue != null && !string.IsNullOrEmpty(editValue.ToString()) &&
                treeList.KeyFieldName != DisplayMember)
            {
                DataTable dt = GetTreeTable();
                if (dt != null)
                {
                    result = "";
                    string[]parts = result.Split(new string[] { MultiSelectSeparator }, StringSplitOptions.RemoveEmptyEntries);
                    foreach (string value in parts)
                    {
                        DataRow r = dt.SelectFirstRow(treeList.KeyFieldName+ " = " + value.EscapeSql());
                        if (r != null)
                        {
                            result = r[DisplayMember].ToString();
                        }
                    }
                }
            }
            return result;
        }
    }

    [UserRepositoryItem("Register")]
    public class RepositoryItemTreeLookUpEdit : RepositoryItemPopupContainerEdit
    {
        static RepositoryItemTreeLookUpEdit()
        {
            Register();
        }
        public static void Register()
        {
            EditorRegistrationInfo.Default.Editors.Add(
                new EditorClassInfo("TreeLookUpEdit", typeof(TreeLookUpEdit),
                    typeof(RepositoryItemTreeLookUpEdit),
                    typeof(DevExpress.XtraEditors.ViewInfo.LookUpEditViewInfo),
                    new DevExpress.XtraEditors.Drawing.ButtonEditPainter(),
                    true,
                    null));
        }
        TreeLookUpEditPopUpControl ctrl = new TreeLookUpEditPopUpControl();
        public RepositoryItemTreeLookUpEdit()
        {
            this.PopupControl = ctrl;
        }
        public RepositoryItemTreeLookUpEdit(BaseEdit edit)
        {
            this.PopupControl = ctrl;
            SetOwnerEdit(edit);
        }

        public override BaseEdit CreateEditor()
        {
            return new TreeLookUpEdit();
        }
        public override void Assign(RepositoryItem item)
        {
            base.Assign(item);
            if (item is RepositoryItemTreeLookUpEdit)
            {
                RepositoryItemTreeLookUpEdit source = (item as RepositoryItemTreeLookUpEdit);
                this.DataSource = source.DataSource;
                this.KeyFieldName = source.KeyFieldName;
                this.ParentFieldName = source.ParentFieldName;
                this.DisplayMember = source.DisplayMember;
            }
        }
        public string MultiSelectSeparator
        {
            get { return (this.PopupControl as TreeLookUpEditPopUpControl).MultiSelectSeparator; }
            set { (this.PopupControl as TreeLookUpEditPopUpControl).MultiSelectSeparator = value; }
        }
        public bool MultiSelect
        {
            get { return (this.PopupControl as TreeLookUpEditPopUpControl).MultiSelect; }
            set
            {
                (this.PopupControl as TreeLookUpEditPopUpControl).MultiSelect = value;
                this.ShowPopupCloseButton = !value;
            }
        }
        public string DisplayMember
        {
            get { return (this.PopupControl as TreeLookUpEditPopUpControl).DisplayMember; }
            set { (this.PopupControl as TreeLookUpEditPopUpControl).DisplayMember = value; }
        }

        [Category("Tree"),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public TreeList TreeList
        {
            get
            {
                if (PopupControl != null)
                {
                    return (this.PopupControl as TreeLookUpEditPopUpControl).TreeList;
                }
                return null;
            }
        }

        [Description("Gets or sets the object used as the data source for the current TreeList control.")]
        [Category("Data")]
        [DefaultValue("")]
        [AttributeProvider(typeof(IListSource))]
        public object DataSource
        {
            get
            {
                if (TreeList != null)
                    return TreeList.DataSource;
                return null;
            }
            set
            {
                TreeList.DataSource = value;
            }
        }

        public string KeyFieldName
        {
            get { if(TreeList!=null)
                return TreeList.KeyFieldName;
            return null;
            }
            set { TreeList.KeyFieldName = value; }
        }

        public string ParentFieldName
        {
            get { if(TreeList!=null)
                return TreeList.ParentFieldName;
            return null;
            }
            set { TreeList.ParentFieldName = value; }
        }

        protected override DevExpress.XtraEditors.Controls.ConvertEditValueEventArgs DoFormatEditValue(object val)
        {
            if(MultiSelect && DisplayMember != KeyFieldName && val.IsNotNull())
                return new DevExpress.XtraEditors.Controls.ConvertEditValueEventArgs(ctrl.GetDisplayValue(val));
            else
                return base.DoFormatEditValue(val);
        }
    }

    public class TreeLookUpEdit : PopupContainerEdit, ISupportInitialize
    {
        public TreeLookUpEdit()
        {

        }

        protected override void CreateRepositoryItem()
        {
            this.fProperties = new RepositoryItemTreeLookUpEdit(this);
        }

        [Description("Specifies settings specific to the current editor."),
        Category("Properties"),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public new RepositoryItemTreeLookUpEdit Properties
        {
            get { return fProperties as RepositoryItemTreeLookUpEdit; }
        }

        protected override void DoShowPopup()
        {
            if (this.Properties.ReadOnly)
            {
                return;
            }
            base.DoShowPopup();
        }
        protected override void OnPopupShown()
        {
            base.OnPopupShown();
            TreeLookUpEditPopUpControl ctrl = this.Properties.PopupControl as TreeLookUpEditPopUpControl;
            if (ctrl != null)
                ctrl.SelectItem(this.EditValue);
        }
        
        #region ISupportInitialize Members

        public void BeginInit()
        {
            this.Properties.BeginInit();
        }

        public void EndInit()
        {
            this.Properties.EndInit();
        }

        #endregion
    }
}
